from tkinter import *
from tkinter import ttk, font, filedialog as fd
import shutil, os, ctypes, pyglet
from fractions import Fraction
from PIL import ImageTk, Image, ImageOps, ImageDraw, ImageFont
import Program
import MyPantry
from Ingredient import Ingredient
from In_refrigerator import In_refrigerator
from In_cabinet import In_cabinet

class In_cabinet_frame(Frame):
    """
    Purpose:
        frame to view and change ingredients in the cabinet
    Instance variables:
        self.cabinet_label: title label displaying "cabinet Food"
        self.remove_labels_frames_dict: dictionary of remove label frames
        self.remove_labels_dict: dictionary of remove labels
        self.top_frame: frame containing labels of ingredients in the cabinet
        self.remove_button: button to remove ingredient from cabinet
        self.add_labels_dict: dictionary of add labels
        self.divider_line: line dividing add and remove ingredients
        self.ingredients_combo_box_clicked: bool if ingredients combo box has
            been clicked
        self.ingredients_combo_box: combo box to search ingredients to add
        self.middle_frame: frame containing the remove ingredients labels
        self.add_button: button that adds ingredients to the cabinet
        self.done_button: closes this frame
    Methods:
        ingredients_combo_box_clicked_event: toggles the ingredients combo
            box clicked to true
        update_remove_labels: displays and binds the remove ingredients labels
        remove_label_clicked: handles what happens when remove
            label is clicked, highlighting ect
        remove_ingredient: removes the ingredient from the cabinet list
        update_add_labels: displays and binds the add ingredients labels
        add_label_clicked: handles what happens when add
            label is clicked, highlighting ect
        add_ingredient: adds the ingredient from the cabinet list
        update_combo_box: updates the search ingredient combo box to show searched
            ingredients
    """

    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.label_color = "SystemButtonFace"
        self.label_text_color = "black"
        self.label_color_clicked = "light gray"
        self.label_text_color_clicked = "black"
        self.cabinet_label = Label(
            self, text="Cabinet Food", font=Program.Program.resizing_title_font
        )
        self.cabinet_label.pack(fill="x", pady=10)

        self.remove_labels_frames_dict = {}
        self.remove_labels_dict = {}
        self.top_frame = Frame(self)
        self.top_frame.pack()
        self.update_remove_labels()

        self.remove_button = Button(
            self,
            text="Remove Ingredient",
            command=lambda: self.remove_ingredient(),
        )
        self.remove_button.pack()

        self.add_labels_dict = {}

        self.divider_line = ttk.Separator(self, orient="horizontal")
        self.divider_line.pack(fill="x", pady=5)
        self.ingredients_combo_box_clicked = False

        self.ingredients_combo_box = ttk.Combobox(self, height=5)
        self.ingredients_combo_box.set("Search Ingredient")
        self.ingredients_combo_box.pack()
        self.ingredients_combo_box.bind(
            "<KeyRelease>", lambda event: self.update_add_labels(event)
        )
        self.ingredients_combo_box.bind(
            "<<ComboboxSelected>>", lambda event: self.update_add_labels()
        )
        self.ingredients_combo_box.bind(
            "<Button-1>",
            lambda _: (
                (
                    Program.Program.controller.default_combo_value_clear(
                        self.ingredients_combo_box, "Search Ingredient"
                    ),
                    self.ingredients_combo_box_clicked_event(),
                ),
            )
            if not self.ingredients_combo_box_clicked
            else None,
        )
        self.middle_frame = Frame(self)
        self.middle_frame.pack()
        self.update_add_labels()

        self.add_button = Button(
            self, text="Add Ingredient", command=lambda: self.add_ingredient()
        )
        self.add_button.pack(pady=5)

        self.done_button = Button(
            self,
            text="Done",
            command=lambda: Program.Program.controller.change_frames(MyPantry.MyPantry),
        )
        self.done_button.pack(side="bottom", pady=(0, 20))

    def ingredients_combo_box_clicked_event(self):
        self.ingredients_combo_box_clicked = True

    def update_remove_labels(self):
        for labels in tuple(self.remove_labels_dict.values()):
            labels.destroy()
        for frames in tuple(self.remove_labels_frames_dict.values()):
            frames.destroy()
        self.remove_labels_dict = {}
        self.remove_labels_frames_dict = {}
        list_of_items = In_cabinet.cabinet_list
        for row in range(0, len(list_of_items), 5):
            self.remove_labels_frames_dict[row] = Frame(self.top_frame)
            self.remove_labels_frames_dict[row].config(bg=self.label_color)
            self.remove_labels_frames_dict[row].pack()
            for ingredient_index in range(row, min(row + 5, len(list_of_items))):
                self.remove_labels_dict[list_of_items[ingredient_index]] = Label(
                    self.remove_labels_frames_dict[row],
                    text=list_of_items[ingredient_index] + ",",
                )
                self.remove_labels_dict[list_of_items[ingredient_index]].grid(
                    row=0, column=ingredient_index % 5
                )
                self.remove_labels_dict[list_of_items[ingredient_index]].config(
                    bg=self.label_color,
                    fg=self.label_text_color,
                    font=Program.Program.resizing_pantry_font,
                )
                self.remove_labels_dict[list_of_items[ingredient_index]].bind(
                    "<Button-1>", lambda event: self.remove_label_clicked(event)
                )
        self.last_clicked_remove = None
        if len(self.remove_labels_dict) > 0:
            self.remove_labels_dict[list_of_items[-1]]["text"] = (
                list_of_items[ingredient_index] + " "
            )

    def remove_label_clicked(self, event):
        if self.last_clicked_remove != None:
            if (
                self.last_clicked_remove
                == self.remove_labels_dict[event.widget.cget("text")[:-1]]
            ):
                self.last_clicked_remove.configure(
                    bg=self.label_color, fg=self.label_text_color
                )
                self.last_clicked_remove = self.remove_labels_dict[
                    event.widget.cget("text")[:-1]
                ]
                self.last_clicked_remove = None
            else:
                self.last_clicked_remove.configure(
                    bg=self.label_color, fg=self.label_text_color
                )
                self.last_clicked_remove = self.remove_labels_dict[
                    event.widget.cget("text")[:-1]
                ]
                self.last_clicked_remove.configure(
                    bg=self.label_color_clicked, fg=self.label_text_color_clicked
                )
        else:
            self.last_clicked_remove = self.remove_labels_dict[
                event.widget.cget("text")[:-1]
            ]
            self.last_clicked_remove.configure(
                bg=self.label_color_clicked, fg=self.label_text_color_clicked
            )

    def remove_ingredient(self):
        if self.last_clicked_remove != None:
            In_cabinet.remove_ingrdient(self.last_clicked_remove.cget("text")[:-1])
            Program.Program.update_pantry()

    def update_add_labels(self, event=""):
        for labels in tuple(self.add_labels_dict.values()):
            labels.destroy()
        search_string = self.ingredients_combo_box.get().upper()
        if (
            not self.ingredients_combo_box_clicked
            and search_string == "SEARCH INGREDIENT"
        ):
            search_string = ""
        self.add_labels_dict = {}
        found_ingredients_dict = {}
        for ingredient_name in Ingredient.ingredients_dict:
            if (
                ingredient_name not in In_refrigerator.refrigerator_list
                and ingredient_name not in In_cabinet.cabinet_list
            ):
                indx = ingredient_name.upper().find(search_string)
                if indx != -1:
                    found_ingredients_dict.setdefault(indx, list())
                    found_ingredients_dict[indx].append(ingredient_name)
        self.ingredients_based_on_search_list = []
        for key in sorted(tuple(found_ingredients_dict.keys())):
            self.ingredients_based_on_search_list += sorted(found_ingredients_dict[key])
        list_of_items = self.ingredients_based_on_search_list
        last_ingredient_added_index = None
        for ingredient_index in range(0, min(5, len(list_of_items))):
            self.add_labels_dict[list_of_items[ingredient_index]] = Label(
                self.middle_frame, text=list_of_items[ingredient_index] + ","
            )
            self.add_labels_dict[list_of_items[ingredient_index]].grid(
                row=0, column=ingredient_index
            )
            self.add_labels_dict[list_of_items[ingredient_index]].config(
                bg=self.label_color,
                fg=self.label_text_color,
                font=Program.Program.resizing_pantry_font,
            )
            self.add_labels_dict[list_of_items[ingredient_index]].bind(
                "<Button-1>", lambda event: self.add_label_clicked(event)
            )
            last_ingredient_added_index = ingredient_index
        if last_ingredient_added_index != None:
            self.add_labels_dict[list_of_items[last_ingredient_added_index]]["text"] = (
                list_of_items[last_ingredient_added_index] + " "
            )
        self.last_clicked_add = None
        self.update_combo_box(list_of_items)

    def add_label_clicked(self, event):
        if self.last_clicked_add != None:
            if (
                self.last_clicked_add
                == self.add_labels_dict[event.widget.cget("text")[:-1]]
            ):
                self.last_clicked_add.configure(
                    bg=self.label_color, fg=self.label_text_color
                )
                self.last_clicked_add = self.add_labels_dict[
                    event.widget.cget("text")[:-1]
                ]
                self.last_clicked_add = None
            else:
                self.last_clicked_add.configure(
                    bg=self.label_color, fg=self.label_text_color
                )
                self.last_clicked_add = self.add_labels_dict[
                    event.widget.cget("text")[:-1]
                ]
                self.last_clicked_add.configure(
                    bg=self.label_color_clicked, fg=self.label_text_color_clicked
                )
        else:
            self.last_clicked_add = self.add_labels_dict[event.widget.cget("text")[:-1]]
            self.last_clicked_add.configure(
                bg=self.label_color_clicked, fg=self.label_text_color_clicked
            )

    def add_ingredient(self):
        if self.last_clicked_add != None:
            ingredient_name = self.last_clicked_add.cget("text")[:-1]
            In_cabinet.add_ingredient(ingredient_name)
            Program.Program.update_pantry()
            self.update_combo_box()

    def update_combo_box(self, lst=None):
        search_string = self.ingredients_combo_box.get().upper()
        if (
            not self.ingredients_combo_box_clicked
            and search_string == "SEARCH INGREDIENT"
        ):
            search_string = ""
        if lst == None:
            found_ingredients_dict = {}
            for ingredient_name in Ingredient.ingredients_dict:
                if (
                    ingredient_name not in In_refrigerator.refrigerator_list
                    and ingredient_name not in In_cabinet.cabinet_list
                ):
                    indx = ingredient_name.upper().find(search_string)
                    if indx != -1:
                        found_ingredients_dict.setdefault(indx, list())
                        found_ingredients_dict[indx].append(ingredient_name)
            self.ingredients_based_on_search_list = []
            for key in sorted(tuple(found_ingredients_dict.keys())):
                self.ingredients_based_on_search_list += sorted(
                    found_ingredients_dict[key]
                )
            self.ingredients_combo_box["values"] = self.ingredients_based_on_search_list
        else:
            self.ingredients_combo_box["values"] = lst

    def change_colors(self, bg_color, primary_color, primary_variant, secondary_color):
        elevation_1_color = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(bg_color), (255, 255, 255), 0.05
            )
        )
        if Program.Program.light_mode:
            button_text_color = "#FFFFFF"
            label_color = Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(elevation_1_color), (0, 0, 0), 0.87
                )
            )
        else:
            button_text_color = "#000000"
            label_color = Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(elevation_1_color), (255, 255, 255), 0.87
                )
            )
        self.label_color_clicked = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(bg_color), (255, 255, 255), 0.16
            )
        )
        self.label_text_color_clicked = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(self.label_color_clicked),
                (255, 255, 255),
                0.87,
            )
        )
        self.label_color = elevation_1_color
        self.label_text_color = label_color
        self.config(bg=bg_color)
        self.top_frame.config(bg=bg_color)
        self.middle_frame.config(bg=bg_color)
        self.cabinet_label.config(bg=elevation_1_color, fg=label_color)
        self.update_add_labels()
        self.update_remove_labels()
        self.ingredients_combo_box.configure(
            style="colored.TCombobox",
        )
        self.ingredients_combo_box.tk.eval(
            f"[ttk::combobox::PopdownWindow %s].f.l configure -foreground {label_color} -background {elevation_1_color}"
            % self.ingredients_combo_box
        )
        primary_color_text = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(primary_color),
                Program.Program.convert_hex_to_rgb(button_text_color),
                0.87,
            )
        )
        self.remove_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            primary_color_text,
            "Remove Ingredient",
            self.remove_button.winfo_width(),
            self.remove_button.winfo_height(),
            22,
        )
        self.remove_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.remove_button_image,
        )
        self.add_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            primary_color_text,
            "Add Ingredient",
            self.add_button.winfo_width(),
            self.add_button.winfo_height(),
            22,
        )
        self.add_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.add_button_image,
        )
        self.done_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            primary_color_text,
            "Done",
            self.done_button.winfo_width(),
            self.done_button.winfo_height(),
            22,
        )
        self.done_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.done_button_image,
        )